import QtQuick 1.1
import VPlay 1.0
import Box2D 1.0
import "../levelLogic.js" as LevelLogic
import "../entities"

Item {
    property string levelName: "Level2"
    id: level
    // use the logical size as the level size
    width:gameScene.width

    // flag to indicate if the level was started or not
    property bool started: false

    // just as an abbreviation of typing, so instead of scene.gridSize just gridSize can be written in this file
    property real gridSize: gameScene.gridSize

    // available columns for creating roostts - the current logical scene width is 320, gridSize is 48, so 6 and a half roosts can be displayed horizontally
    property int roostColumns: width/gridSize

    // gets used to measure how much the level was moved downwards in the last frame - if this is bigger than gridSize, a new row will be created in onYChanged
    property real lastY: 0

    // how many new rows were created, it starts with 0 if the level has y position 0, and then gets increased with every gridSize
    // gets initialized in onCompleted
    property real currentRow: height / gridSize

    // this is needed so an alias can be created from the main window!
    property alias player: player

    // specifies the px/second how much the level moves
    property real levelMovementSpeedMinimum: 60 // in km/h
    property real levelMovementSpeedMaximum: 100
    // after 30seconds, the maximum speed will be reached - if you set this too high, also increase the gravity so the chicken falls faster than the level moves
    property int levelMovementDurationTillMaximum: 30

    // with 9% probability, a roost will get created in a row for any column
    // if it gets set too low, the game will be unplayable because too few roosts are created, so balance this with care!
    property real platformCreationProbability: 0.15
    // probability of 30% to create a corn on top of the roost, so in 3 of 10 roosts there will be a corn created
    property real coinCreationPropability: 0.3
    // windows get created randomly as well - they only have visual effect, but dont set too high because then it looks boring
    property real windowCreationProbability: 0.05
    // this avoids creating too many windows, so not possible to have more than 2 on a scene with this code!
    property real minimumWindowHeightDifference: 300

    // is needed internally to avoid creating too many windows close to each other
    property int lastWindowY: 0

    // the background images are moved up by this offset so on widescreen devices the full background is visible
    property real __yOffsetForWindow: gameScene.__yOffsetForAbsoluteWindowCoordinates

    // gets emitted when a BorderRegion.onPlayerCollision() is received
    signal gameLost

    Component.onCompleted: {

        // this creates some roosts, coins and windows beforehand, so they dont need to be created at runtime
        preCreateEntityPool();

        //startGame()// is called in ChickenOutbreakScene.enterScene()
    }

    // tried to do several ways to trigger start and stop
    // of the level, finally used this onVisibleChanged:  -
    // -> This seems to be dirty, there should be a better way
    // to do this, but we don't know which...
    onVisibleChanged:
    {
        //console.debug("############################");
        // start the game
        if (visible && !started)
        {
            started = true;
            //preCreateEntityPool();
            startGame();
        }
        // stop the game
        else if (!visible && started)
        {
            stopGame();
        }

    }

    function preCreateEntityPool() {

        // dont pool entities on Sym & meego - creation takes very long on these platforms
        if(system.isPlatform(System.Meego) || system.isPlatform(System.Symbian))
            return;

        entityManager.createPooledEntitiesFromUrl(Qt.resolvedUrl("../entities/Roost.qml"), 20);

        entityManager.createPooledEntitiesFromUrl(Qt.resolvedUrl("../entities/Coin.qml"), 10);
    }

    function stopGame() {
        started = false;
        levelMovementAnimation.stop();

        // this function automatically pools all entities which have poolingEnabled set to true
        // and it ignores the entities that have preventFromRemovalFromEntityManager set to true

        player.stopSmoke();
        entityManager.removeAllEntities();
        // Just go back to the menu, sending signal made problems
        // because of dynamic levels...
        backPressed();

        // only use this for debugging, whena game should immediately be started after it was stopped
        //startGame();
    }

    // initialize level data - this function can be called multiple times, so every time a new game gets started
    // it is called from ChickenOutbreakScene.enterScene()
    function startGame() {
        console.debug("Level: startGame()");

        // it is important that lastY is set first, so the dy in onYChanged will be 0 and no new row is created
        currentRow = 0; //height / gridSize;
        lastY = 0;

        level.y = 0;

        player.x = gameScene.width/2;
        player.y = gameScene.height - 100;

        player.carHealth = 100;
        player.fuel = 100;
        player.rockets = 10;
        player.bonusScore = 0;

        // this is required, otherwise after the game the chicken would still navigate left or right if no mouse release happened before, or when coming from the main scene it might still have the old direction
        player.controller.xAxis = 0;
        //player.controller.yAxis = 0;

        // start positioned on the window top

        // this must be set BEFORE createRandomRowForRowNumber() is called!
        lastWindowY = 0;

        for(var i=0; i<5; i++) {
            LevelLogic.createRandomRowForRowNumber(i);
        }

        levelMovementAnimation.velocity = levelMovementSpeedMinimum;
        levelMovementAnimation.start();
    }

    // tried to add walls here that would border the game scene
    // did not really work because of the physics world, set it
    // via listeners on X instead
//    Wall {
//        id: border_bottom

//        height: 2
//        anchors {
//            left: parent.left
//            right: parent.right
//            bottom: parent.bottom
//        }
//    }

//    Wall {
//        id: border_left
//        width: 2
//        anchors {
//            top: parent.top
//            bottom: parent.bottom
//            left: parent.left
//        }
//    }

//    Wall {
//        id: border_right
//        width: 2
//        anchors {
//            top: parent.top
//            bottom: parent.bottom
//            right: parent.right
//        }
//    }


    // this is the offset of the 2 backgrounds
    // make the offset a litte bit smaller, so no black background shines through when they are put below each other
    property real levelBackgroundHeight: levelBackground.height*levelBackground.scale-1

    // handles the repositioning of the background, if they are getting out of the scene
    // internally, 4 images are created below each other so it appears to the user as being one continuous background
    ParallaxScrollingBackground {
        id: levelBackground
        y: -level.y
        sourceImage: "../img/MostWonders.png"
        // do not mirror it vertically, because the image is prepared to match on the top and the bottom
        mirrorSecondImage: false
        movementVelocity: Qt.point(0, levelMovementAnimation.velocity)
        running: levelMovementAnimation.running // start non-running, gets set to true in startGame
    }

    // start in the center of the scene, and a little bit below the top
    // the player will fall to the playerInitialBlock below at start
    Player {
        id: player

        x: gameScene.width/2
        y: gameScene.height - 50

        // this guarantees the player is in front of the henhouseWindows
        z: 3

    }

    // this guarantees the ball doesnt fall through in the beginning
    // -> we don't need this
    //    Roost {
    //        id: lowerBlock
    //        // this id is used in BorderRegion to prevent this block from being removed!
    //        entityId: "playerInitialBlock"
    //        x: gameScene.width/2
    //        y: 3.5*gridSize // just a random position a little bit below the player

    //        // this keeps the entity from removeAllEntities()
    //        preventFromRemovalFromEntityManager: true
    //    }

    // the game win is defined in the player instead...
//    BorderRegion {
//        x: gameScene.gameWindowAnchorItem.x
//        width: 0.0 // make bigger than the window, because the roost can stand out of the scene on the right side when the gridSize is not a multiple of the scene.width (which it currently is: 320/48=6.6) and thus if the player would stand on the right side no collision would be detected!
//        variationType: "topRegion"

//        // this height is not important, could also be set to 1 or anything else
//        height: 1

//        // this is important: the topRegion moves with the level, because the positions of the physics bodies do not move with the level position!
//        // so the topRegion is always on the top of the scene + the height of the highest item (the window)
//        // add 60 pixels (which is the height of the window), so it doesnt get removed while it is still visible!
//        y: -level.y + height  //+ __yOffsetForWindow + height

//        onPlayerCollision: {
//            console.debug("PLAYER COLLIDED WITH topRegion, level.y:", level.y, ", player.y:", player.y)
//            // emit the gameLost signal, which is handled in ChickenOutbreakScene
//            stopGame();
              // Game WIN
//        }
//    }

    BorderRegion {
        // make it so big that the player will still loose if he navigates to the right or left of the screen and then falls down
        width: gameScene.gameWindowAnchorItem.width*4
        anchors.horizontalCenter: parent.horizontalCenter

        height: 20
        // the BorderRegion is always out of the visual scene, so it is never visible
        // it moves with the level
        y: -level.y + gameScene.gameWindowAnchorItem.height //-height

        variationType: "bottomRegion"

        onPlayerCollision: {
            console.debug("PLAYER COLLIDED WITH BorderRegion, level.y:", level.y, ", player.y:", player.y)
            // emit the gameLost signal, which is handled in ChickenOutbreakScene
            stopGame();
            // Game LOST
            //gameScene.window.state = "gamelost";
        }
    }


    MovementAnimation {
        id: levelMovementAnimation
        property: "y"
        // this is the movement in px per second, start with very slow movement, 10 px per second
        velocity: levelMovementSpeedMinimum
        // running is set to false - call start() here
        // increase the velocity by this amount of pixels per second, so it lasts minVelocity/acceleration seconds until the maximum is reached!
        // i.e. -90/-2 = 45 seconds
        acceleration: 0 //(levelMovementSpeedMaximum-levelMovementSpeedMinimum) / levelMovementDurationTillMaximum
        target: level

        // limit the maximum v to 100 px per second - it must not be faster than the gravity! this is the absolute maximum, so the chicken falls almost as fast as the background moves by! so rather set it to -90, or increase the gravity
        minVelocity: -levelMovementSpeedMaximum

        //onVelocityChanged: console.debug("velocity changed to:", velocity)
    }

    // when the level gets moved down, check if the difference between last level y position and the current one is greater than gridSize - if so, create a new row
    onYChanged: {
        // y gets more and more positive
        //console.debug(y, " $$$$$$$$$$$$$$$$$$$$$ Y")
        var dy = level.y - lastY;
        //console.debug("level.dy:", -dy, "currentRow:", currentRow, ", y:", -y, ", lastY:", -lastY)
        if(dy > gridSize) {

            var amountNewRows = (dy/gridSize).toFixed();
            console.debug(amountNewRows, "new rows are getting created...")

            // if y changes a lot within the last frame, multiple rows might get created
            // this doesnt happen with fixed dt, but it could happen with varying dt where more than 1 row might need to be created because of such a big y delta
            for(var i=0; i<amountNewRows; i++) {
                // this guarantees it is created outside of the visual screen
                LevelLogic.createRandomRowForRowNumber(currentRow);
                currentRow--;
                // it's important to decrease lastY like that, not setting it to y!
                lastY += gridSize
            }
        }

        // this was used to set the player to a fixed position, but
        // it was very hard on the performance of the game, it became
        // very laggy
//        player.y = -level.y + height - 50;

        // TODO: use a bitmap font for text updating which is much faster -> this feature is not supported by V-Play yet, contact us if you would need it at team@v-play.net
        // for performance reasons, disable the score updating every frame, which is expensive with the text element because a texture is recreated every time the text changes!
        if(enableConstantScoreTextUpdating)
            player.score = -level.y.toFixed()
        else
            // divide by an arbitrary number, so the text doesnt get changed every frame which is bad for performance as it is no bitmap font yet!
            player.score = -(level.y/40).toFixed()
    }

    // ------------------- for debugging only ------------------- //
//    function pauseGame() {
//        console.debug("pauseGame()")
//        levelMovementAnimation.stop();
//    }
//    function resumeGame() {
//        console.debug("resumeGame()")
//        levelMovementAnimation.start();
//    }

//    function restartGame() {
//        console.debug("restartGame()")
//        stopGame();
//        startGame();
//    }
}
